		TITLE	LIDATA - Copyright (c) 1994 by SLR Systems

		INCLUDE	MACROS
		INCLUDE	SEGMENTS


		PUBLIC	LIDATA_PROC,FORREF_MAJOR_MOVE,FIXDS_MOVER


		.DATA

		EXTERNDEF	FIX2_LD_TYPE:BYTE

		EXTERNDEF	EXETABLE:DWORD,FIX2_LDATA_EOR:DWORD,SRCADR:DWORD,FIX2_SM_START:DWORD,FIX2_STACK_DELTA:DWORD

		EXTERNDEF	MAJOR_MOVE_ROUTINE:DWORD


		.CODE	PASS2_TEXT

		EXTERNDEF	MOVE_LDATA_1:PROC,CONVERT_SUBBX_TO_EAX:PROC,OBJ_PHASE:PROC,REL_CHK_LIDATA:PROC,LIBASE_FLUSH:PROC
		EXTERNDEF	_abort:proc


LIDATA_PROC	PROC
		;
		;
		;
		PUSHM	EDI,ESI

		MOV	MAJOR_MOVE_ROUTINE,OFF LI_MOVE_LDATA_1

		PUSHM	EBX,EBP

		MOV	ESI,EAX
		MOV	AL,FIX2_LD_TYPE

		MOV	EDI,-1			;KEEP 32 BITS
		MOV	EBP,6			;UPDATE POINTER BY 4

		AND	AL,MASK BIT_32
		JNZ	L1$

		MOV	EDI,0FFFFH		;OOPS, JUST KEEP 16 BITS
		SUB	EBP,2			;UPDATE POINTER BY 2

L1$:
		CALL	LIDATA_PROC1

		POPM	EBP,EBX,ESI,EDI

		RET

LIDATA_PROC	ENDP


LIDATA_PROC_LOOP	PROC	NEAR

		CALL	LIDATA_LOOPER
LIDATA_PROC1::
		;
		;ESI IS LIDATA RECORD
		;EDX IS TARGET ADDRESS LOGICAL
		;
		CMP	FIX2_LDATA_EOR,ESI
		JA	LIDATA_PROC_LOOP

		JZ	LIBASE_FLUSH		;FLUSH ANY WAITING RELOCS...

		CALL	OBJ_PHASE
		JMP	_abort

LIDATA_PROC_LOOP	ENDP


LIDATA_LOOPER::
		MOV	ECX,1		;BLOCK COUNT
		MOV	EBX,1		;REPEAT COUNT

LIDATA		PROC	NEAR	PRIVATE
		;
		;ESI IS RECORD
		;
		PUSH	EDX		;LOGICAL ADDRESS AT THIS POINT
		PUSH	EBX		;REPEAT COUNT AT THIS POINT

		TEST	ECX,ECX
		JZ	GENERATE
BLOCK_LOOP:
		MOV	EBX,[ESI]	;GET NEXT REPEAT FACTOR
		ADD	ESI,EBP		;KEEP 16 OR 32 BITS OF IT...

		PUSH	ECX		;SAVE BLOCK COUNT
		AND	EBX,EDI		;EBX IS REPEAT COUNT

		MOV	ECX,[ESI-2]	;BLOCK COUNT

		AND	ECX,0FFFFH
		CALL	LIDATA

		POP	ECX		;BLOCK COUNT

		DEC	ECX
		JNZ	BLOCK_LOOP	;DO LOOP AGAIN
GENERATE_RET:
		POP	EBX		;REPEAT COUNT
		POP	ECX		;OLD LOGICAL ADDRESS

		DEC	EBX
		JNZ	DUPLICATE_LAST
G_RET_RET:
		RET			;BACK TO PREVIOUS LOOP?

GENERATE:
		;
		;GENERATE A FEW BYTES OF CODE...
		;
		XOR	ECX,ECX
		LEA	EAX,[ESI+1]

		MOV	CL,[ESI]
		PUSH	EDX

		PUSH	ECX
		CALL	LI_MOVE_LDATA_1	;EAX IS RECORD DATA, EDX IS TARGET
					;LOGICAL, ECX IS BYTE COUNT
		POPM	ECX,EDX

		MOV	ESI,EAX
		ADD	EDX,ECX

		POP	EBX		;REPEAT COUNT
		POP	ECX		;OLD LOGICAL ADDRESS

		DEC	EBX
		JZ	G_RET_RET

DUPLICATE_LAST:
		;
		;COPY FROM EXE TO EXE, IF A BYTE, COPY 1 FIRST, THEN USE MOVSW
		;
		PUSHM	ESI,EDX
		;
		;EDX IS TARGET LOGICAL ADDRESS
		;SRCADR IS SOURCE LOGICAL.
		;EBX * (TARGET-SOURCE) = # OF BYTES TO MOVE
		;
		MOV	SRCADR,ECX	;PLACE THIS BEGAN
		SUB	EDX,ECX		;EDX = TARGET-SOURCE

		MOV	EAX,EBX
		MOV	ECX,EDX		;SAVE DELTA

		MUL	EDX		;EAX IS # OF BYTES TO MOVE
		;
		;IF DELTA = ODD  ->  MOVE SMALLER OF DELTA AND # TO MOVE
		;ECX IS DELTA, EAX IS # TO MOVE
		;
		CMP	EAX,320		;SKIP ALL THIS IF LESS THAN 320 BYTES
		JC	FINAL_BYTE

		TEST	CL,1
		JZ	TRY_386

		POP	EDX
		CALL	DOIT

		JZ	GO_RET

		PUSH	EDX
TRY_386:

if 1
		;
		;OK, DELTA NOW EVEN, IF IS_386, MAKE SURE DELTA IS DWORD
		;
		TEST	CL,3
		JZ	TRY_EVEN

		POP	EDX
		CALL	DOIT

		JZ	GO_RET

		PUSH	EDX
		MOV	EBX,3
TRY_EVEN:
else
		MOV	EBX,1
endif
		MOV	EDX,SRCADR

		ADD	EDX,FIX2_STACK_DELTA

		SUB	EDX,FIX2_SM_START

		TEST	EDX,EBX
		JZ	FINAL
		;
		;NEED TO ADJUST SOURCE...
		;CX:BX IS DELTA, SI:AX IS # TO MOVE
		;
		MOV	EDX,SRCADR

		AND	EDX,EBX
		INC	EBX

		SUB	EBX,EDX			;EBX IS # NEEDED FOR ALIGNMENT
		;
		;USE SMALLER OF # TO MOVE AND EBX
		;
		CMP	EAX,EBX
		JNC	USE_EBX
		;
		;USE SI:AX
		;
		POP	EDX
		CALL	DOIT

		JNZ	FINAL1
GO_RET:
		POP	ESI
		RET

USE_EBX:
;		MOV	BP_1,DI
		POP	EDX

		PUSHM	ECX,EAX

		MOV	BP_1,EAX
		MOV	EAX,EBX

		PUSH	EAX
		CALL	DOIT
		;
		;NOW NEED TO UPDATE REAL COUNT AND SRCADR
		;
		POP	EBX
		MOV	ECX,SRCADR

		POP	EAX
		ADD	ECX,EBX

		SUB	EAX,EBX
		MOV	SRCADR,ECX

		POP	ECX		;DELTA IS SAME
		JNZ	FINAL1

		POP	ESI

		RET

FINAL_BYTE:
		;
		;OK, MOVE ALL THATS LEFT
		;
		SETT	MOVE_BYTES

		POP	EDX
		CALL	MAJOR_MOVE

		POP	ESI

		RESS	MOVE_BYTES
		RET

FINAL:
		;
		;OK, MOVE ALL THATS LEFT
		;
		POP	EDX
FINAL1:
		CALL	MAJOR_MOVE
		POP	ESI
		RET

LIDATA		ENDP


MAJOR_MOVE	PROC
		;
		;EAX IS # OF BYTES TO MOVE
		;EDX IS TARGET ADDRESS...
		;SRCADR IS SOURCE ADDRESS
		;
		;MOVE_LDATA_1  ECX = BYTE COUNT, BX=LDATA_SEGMOD, EDX DEST
		;
FORREF_MAJOR_MOVE	LABEL	PROC

		MOV	ECX,SRCADR

		ADD	ECX,FIX2_STACK_DELTA			;IN CASE IT IS A STACK SEGMENT

		SUB	ECX,FIX2_SM_START

FIXDS_MOVER	LABEL	PROC					;CALLED BY FIXDS IN SPECIAL CASE

		PUSH	EBX
		MOV	EBX,ECX

		SHR	EBX,PAGE_BITS
		AND	ECX,PAGE_SIZE-1

		PUSH	ESI
		MOV	ESI,ECX

		LEA	EBX,EXETABLE[EBX*4]
MAJOR_LOOP:
		PUSH	EAX

		MOV	ECX,PAGE_SIZE
		CALL	CONVERT_SUBBX_TO_EAX

		SUB	ECX,ESI
		ADD	ESI,EAX

		POP	EAX

		CMP	ECX,EAX
		JC	USE_MAX

		MOV	ECX,EAX
USE_MAX:
		PUSH	EAX
		MOV	EAX,ESI

		PUSHM	EDX,ECX

		CALL	MAJOR_MOVE_ROUTINE	;EDX IS DEST, EAX SRC, ECX BYTE COUNT

		POPM	ECX,EDX

		XOR	ESI,ESI
		POP	EAX

		ADD	EDX,ECX
		SUB	EAX,ECX

		LEA	EBX,[EBX+4]
		JNZ	MAJOR_LOOP

		POPM	ESI,EBX

		RET

MAJOR_MOVE	ENDP


DOIT		PROC	NEAR
		;
		;CX:BX IS DELTA, SI:AX IS # TO MOVE, DX:DI IS TARGET LOGICAL
		;ECX IS DELTA, EAX IS # TO MOVE, EDX IS TARGET LOGICAL
		;
		;MOVE SMALLER OF DELTA & # TO MOVE
		;
		PUSH	EBX

		PUSHM	ECX,EAX

		CMP	ECX,EAX
		JC	USE_DELTA
USE_NTM:
		MOV	ECX,EAX

USE_DELTA:
		PUSH	EDX
		MOV	EAX,ECX			;EAX IS BYTE COUNT

		MOV	EBX,ECX
		CALL	MAJOR_MOVE

		POPM	EDX,EAX

		ADD	EDX,EBX
		POP	ECX

		ADD	ECX,EBX
		SUB	EAX,EBX

		POP	EBX

		RET

DOIT		ENDP


LI_MOVE_LDATA_1	PROC
		;
		;EDX IS TARGET ADDRESS
		;ECX IS BYTE COUNT
		;EAX IS SOURCE ADDRESS
		;
		;
		;NEED TO DO REL_CHK_LIDATA...
		;
		BITT	CHECK_RELOCATIONS
		JZ	MOVE_LDATA_1

		PUSHM	EDX,ECX,EAX
		CALL	REL_CHK_LIDATA

		POPM	EAX,ECX,EDX
		JMP	MOVE_LDATA_1

LI_MOVE_LDATA_1	ENDP


		.DATA?

		ALIGN	4

BP_1		DD	?


		END

